"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.watch = exports.watchEffect = void 0;
var reactive_1 = require("./reactive");
var utils_1 = require("./utils");
function watchEffect(getter) {
    return reactive_1.effect(getter).stop;
}
exports.watchEffect = watchEffect;
function watch(source, callback) {
    return doWatch(source, callback);
}
exports.watch = watch;
function doWatch(source, cb) {
    var deep = false;
    var getter;
    if (utils_1.isArray(source)) {
        getter = function () {
            source.map(function (s) {
                if (reactive_1.isRef(s)) {
                    return s.value;
                }
                else if (reactive_1.isReactive(s)) {
                    return traverse(s);
                }
                else if (utils_1.isFunction(s)) {
                    return s();
                }
            });
        };
    }
    else if (reactive_1.isRef(source)) {
        getter = function () { return source.value; };
    }
    else if (reactive_1.isReactive(source)) {
        getter = function () { return source; };
        deep = true;
    }
    else if (utils_1.isFunction(source)) {
        getter = function () { return source; };
    }
    else {
        getter = function () { };
    }
    if (cb && deep) {
        var baseGetter_1 = getter;
        getter = function () { return traverse(baseGetter_1()); };
    }
    return reactive_1.effect(getter).stop;
}
function traverse(value, seen) {
    if (seen === void 0) { seen = new Set(); }
    if (!utils_1.isObject(value) || seen.has(value)) {
        return value;
    }
    seen.add(value);
    if (utils_1.isArray(value)) {
        for (var i = 0; i < value.length; i++) {
            traverse(value[i], seen);
        }
    }
    else if (value instanceof Map) {
        value.forEach(function (v, key) {
            // to register mutation dep for existing keys
            traverse(value.get(key), seen);
        });
    }
    else if (value instanceof Set) {
        value.forEach(function (v) {
            traverse(v, seen);
        });
    }
    else {
        for (var key in value) {
            traverse(value[key], seen);
        }
    }
    return value;
}
